﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using FutureCode.Game.Command;
using System;

/// <summary>
/// 影子行为类，辅助人物或怪物进行平滑的行为（移动、攻击、死忘）同步
/// </summary>
public class ShadowBehaviour : MonoBehaviour {

    /// <summary>
    /// 影子对象的统一静态父对象（空对象，便于统一管理影子对象）
    /// </summary>
    public static Transform ShadowParent;
    /// <summary>
    /// 是否正在进行移动操作
    /// </summary>
    public bool Moving = false;
    /// <summary>
    /// 影子移动的速度
    /// </summary>
    public float Speed;
    /// <summary>
    /// 判断追上的间距
    /// </summary>
    public float CloseInterval = 0.35f;
    /// <summary>
    /// 是否启用平滑旋转
    /// </summary>
    public bool UseSmoothRotation = true;
    /// <summary>
    /// 影子来源对象接口
    /// </summary>
    public IMoveableObject OriginObject
    {
        get
        {
            return originObject;
        }
        set
        {
            originObject = value;
            shadow.position = originObject.Position;
            shadow.rotation = originObject.Rotation;
        }
    }
    /// <summary>
    /// 影子或记录点是否被追上
    /// </summary>
    public bool Catched = false;
    /// <summary>
    /// 影子触发器大小
    /// </summary>
    public Vector3 TriggerSize {
        get { return triggerSize; }
        set { triggerSize = value;
            triggerCollider.size = triggerSize;
        }
    }

    Vector3 triggerSize = new Vector3(1, 1, 1);
    IMoveableObject originObject;
    Transform shadow;
    Transform trigger;
    BoxCollider triggerCollider;

    /// <summary>
    /// 行为队列，记录特殊行为（攻击、受伤、死亡等），方便进行特殊行为同步
    /// </summary>
    Queue<BehaviourRecord> behaviourQueue;
    Dictionary<BehaviourType, List<Action>> listeners;

    MeshRenderer meshRenderer;

    void Awake()
    {
        //获取影子父对象
        if (ShadowParent == null)
            ShadowParent = GameObject.Find("Shadows").transform;
        //设置影子对象的父对象
        transform.parent = ShadowParent;
        behaviourQueue = new Queue<BehaviourRecord>();

        listeners = new Dictionary<BehaviourType, List<Action>>();
        listeners.Add(BehaviourType.Attack, new List<Action>());
        listeners.Add(BehaviourType.Dead, new List<Action>());
        listeners.Add(BehaviourType.Injured, new List<Action>());

        shadow = transform.FindChild("Shadow");
        trigger = transform.FindChild("Trigger");
        triggerCollider = trigger.GetComponent<BoxCollider>();

        meshRenderer = shadow.gameObject.AddComponent<MeshRenderer>();
        var mesh = shadow.gameObject.AddComponent<MeshFilter>().mesh;
        mesh.vertices = new Vector3[]
        {
            new Vector3(-0.5f, 0, 0), new Vector3(0, 0, 0.5f), new Vector3(0.5f, 0, 0), new Vector3(0, 0, -0.5f)
        };
        mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
        mesh.RecalculateNormals();

        meshRenderer.enabled = ShadowManager.Instance.Show;
    }

    void Start()
    {

    }

    void OnEnable()
    {
        if (OriginObject == null)
        {
            return;
        }
        behaviourQueue.Clear();
        shadow.position = OriginObject.Position;
        shadow.rotation = OriginObject.Rotation;
    }

    void FixedUpdate()
    {
        if (Moving && behaviourQueue.Count == 0)
        {
            //如果正在移动，根据移动速度改变影子的位置
            shadow.position = shadow.position +
                shadow.forward * Speed * Time.fixedDeltaTime;
        }
    }

    bool following = false;
    BehaviourRecord? currentRecord;
    void Update()
    {
        if (OriginObject == null)
            return;

        bool isNewRecord = false;
        if (currentRecord == null)
        {
            if (HasRecord())
            {
                //若还有剩余记录，获取下一个记录的位置与旋转并赋值给触发器
                currentRecord = NextRecord();
                //Catched = false;
                trigger.position = currentRecord.Value.Position;
                trigger.rotation = currentRecord.Value.Rotation;
                isNewRecord = true;
            }
            else
            {
                //没有剩余记录，触发器位置与旋转为当前影子位置与影子旋转
                if (trigger.position != shadow.position)
                {
                    trigger.position = shadow.position;
                    trigger.rotation = shadow.rotation;
                }
            }
        }
        if (!Catched)
        {
            //如果没有被源对象追赶上，平滑跟随当前记录中的位置或当前影子的位置
            var direction = trigger.position - OriginObject.Position;
            Quaternion lookRotation = Quaternion.LookRotation(direction);
            if (UseSmoothRotation)
            {
                OriginObject.Rotation = Quaternion.Slerp(OriginObject.Rotation, lookRotation, 20 * Time.deltaTime);
            }
            else
            {
                OriginObject.Rotation = lookRotation;
            }
            //if(!following)
                OriginObject.Move();
            following = true;
        }
        else if(following || isNewRecord)
        {
            //当前记录位置或影子位置已被追赶上，执行注册的监听事件或停止源对象移动
            following = false;
            if (currentRecord != null)
            {
                OriginObject.Rotation = trigger.rotation;
                foreach (var a in listeners[currentRecord.Value.Type])
                {
                    a.Invoke();
                }
                currentRecord = null;
            }
            else
            {
                OriginObject.StopMove();
            }
        }
        else
        {
            //影子已经被追赶上，将源对象平滑旋转到影子旋转
            if (UseSmoothRotation)
            {
                OriginObject.Rotation = Quaternion.Slerp(OriginObject.Rotation, trigger.rotation, 10 * Time.deltaTime);
            }
            else
            {
                OriginObject.Rotation = trigger.rotation;
            }
        }
    }

    /// <summary>
    /// 影子开始移动
    /// </summary>
    /// <param name="startPosition">移动开始的位置</param>
    /// <param name="rotation">移动时的旋转</param>
    /// <param name="speed">移动速度</param>
    /// <param name="startTime">移动开始的时间（对方客户端发出移动命令的时间）</param>
    /// <param name="clientTimeNow">当前客户端时间（收到移动命令的时间）</param>
    public void Move(Vector3 startPosition, Quaternion rotation, float speed, DateTime startTime, DateTime clientTimeNow)
    {
        shadow.position = startPosition;
        shadow.rotation = rotation;
        //通过时间差预测当前时刻所在的位置
        shadow.position = PositionPrediction(startPosition, shadow.forward * speed, startTime, clientTimeNow);
        Speed = speed;
        Moving = true;
    }

    /// <summary>
    /// 影子停止移动
    /// </summary>
    /// <param name="stopPosition">停止移动的位置</param>
    /// <param name="rotation">停止移动时的旋转</param>
    public void StopMove(Vector3 stopPosition, Quaternion rotation)
    {
        Moving = false;
        shadow.position = stopPosition;
        shadow.rotation = rotation;
        Speed = 0;
    }

    /// <summary>
    /// 添加行为
    /// </summary>
    /// <param name="position">行为位置</param>
    /// <param name="rotation">行为旋转</param>
    /// <param name="type">行为类型</param>
    public void AddBehaviour(Vector3 position, Quaternion rotation, BehaviourType type)
    {
        shadow.position = position;
        shadow.rotation = rotation;
        var record = new BehaviourRecord(position, rotation, type);
        behaviourQueue.Enqueue(record);
    }
    /// <summary>
    /// 是否有待执行的行为
    /// </summary>
    /// <returns>是否有待执行的行为</returns>
    public bool HasRecord()
    {
        return behaviourQueue.Count > 0;
    }
    /// <summary>
    /// 下一个待执行的行为
    /// </summary>
    /// <returns>待执行的行为记录</returns>
    public BehaviourRecord NextRecord()
    {
        if (behaviourQueue.Count == 0)
            throw new InvalidOperationException("Record queue is empty!");
        return behaviourQueue.Dequeue();
    }
    /// <summary>
    /// 添加行为完成事件监听方法
    /// </summary>
    /// <param name="type">完成的行为类型</param>
    /// <param name="action">监听方法</param>
    public void AddEventListener(BehaviourType type, Action action)
    {
        if (listeners[type].Contains(action))
            return;
        listeners[type].Add(action);
    }
    /// <summary>
    /// 移除行为完成事件监听方法
    /// </summary>
    /// <param name="type">完成的行为类型</param>
    /// <param name="action">要移除的监听方法</param>
    public void RemoveEventListener(BehaviourType type, Action action)
    {
        if (!listeners[type].Contains(action))
            return;
        listeners[type].Remove(action);
    }

    /// <summary>
    /// 清楚行为记录
    /// </summary>
    public void ClearRecords()
    {
        behaviourQueue.Clear();
    }

    /// <summary>
    /// 显示或隐藏影子网格
    /// </summary>
    /// <param name="show"></param>
    public void ShowShadowMesh(bool show)
    {
        meshRenderer.enabled = show;
    }

    /// <summary>
    /// 影子位置预测
    /// </summary>
    /// <param name="startPosition">移动开始的位置</param>
    /// <param name="speed">移动速度</param>
    /// <param name="startTime">移动开始的时间</param>
    /// <param name="predictTime">预测位置的时间</param>
    /// <returns>位置预测结果</returns>
    Vector3 PositionPrediction(Vector3 startPosition, Vector3 speed, DateTime startTime, DateTime predictTime)
    {
        float timeDuration = (float)((predictTime - startTime).TotalMilliseconds) / 1000f;
        return startPosition + speed * timeDuration;
    }
}

/// <summary>
/// 行为记录结构体
/// </summary>
public struct BehaviourRecord
{
    public Vector3 Position;
    public Quaternion Rotation;
    public BehaviourType Type;

    public BehaviourRecord(Vector3 position, Quaternion rotation, BehaviourType type)
    {
        this.Position = position;
        this.Rotation = rotation;
        this.Type = type;
    }
}

/// <summary>
/// 行为类型
/// </summary>
public enum BehaviourType
{
    Attack,
    Injured,
    Dead,
}
